#pragma once
#include "kstlbool.h"

#include <stdlib.h>

#ifdef __cplusplus
extern "C" {
#endif

#define KV_FOR_EACH(handle, it, end)                                                                                   \
    for (KstlVectorIterator(it) = KstlVectorIteratorBegin((handle)), (end) = KstlVectorIteratorEnd((handle));          \
         !KstlVectorIteratorEqual((it), (end));                                                                        \
         KstlVectorIteratorNext(&(it)))

typedef struct KstlVector KstlVector;

typedef struct KstlVectorIterator {
    KstlVector* handle;
    void*       pointer;
} KstlVectorIterator;

KstlVector* KstlVectorInit(size_t itemSize);
KstlVector* KstlVectorInitWithCapacity(size_t itemSize, size_t capacity);
KstlVector* KstlVectorInitWithCapacityAndValue(size_t itemSize, size_t capacity, void* defaultValue);

void KstlVectorRelease(KstlVector* handle);

size_t KstlVectorSize(KstlVector* handle);
size_t KstlVectorCapacity(KstlVector* handle);

int KstlVectorPushBack(KstlVector* handle, void* item);
int KstlVectorPopBack(KstlVector* handle);

const void* KstlVectorData(KstlVector* handle);

void* KstlVectorReadAt(KstlVector* handle, size_t i);
int   KstlVectorWriteAt(KstlVector* handle, size_t i, void* item);

KstlVectorIterator KstlVectorIteratorBegin(KstlVector* handle);
KstlVectorIterator KstlVectorIteratorEnd(KstlVector* handle);

KstlVectorIterator KstlVectorIteratorFromIndex(KstlVector* handle, size_t index);

void KstlVectorIteratorNext(KstlVectorIterator* it);
void KstlVectorIteratorPrev(KstlVectorIterator* it);

KstlVectorIterator KstlVectorIteratorReverseBegin(KstlVector* handle);
KstlVectorIterator KstlVectorIteratorReverseEnd(KstlVector* handle);

void KstlVectorIteratorReverseNext(KstlVectorIterator* it);

bool  KstlVectorIteratorEqual(KstlVectorIterator current, KstlVectorIterator end);
void* KstlVectorIteratorValue(KstlVectorIterator current);

#ifdef __cplusplus
}  // extern "C"
#endif